package cn.jbolt.core.service;

import cn.hutool.core.io.FileTypeUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.file.FileNameUtil;
import cn.jbolt.core.base.JBoltMsg;
import cn.jbolt.core.common.enums.JBoltSystemLogTargetType;
import cn.jbolt.core.consts.JBoltConst;
import cn.jbolt.core.kit.JBoltUserKit;
import cn.jbolt.core.model.JboltFile;
import cn.jbolt.core.service.base.JBoltBaseService;
import cn.jbolt.core.util.JBoltRealUrlUtil;
import cn.jbolt.core.util.JBoltUploadFileUtil;
import com.jfinal.core.JFinal;
import com.jfinal.kit.Okv;
import com.jfinal.kit.Ret;
import com.jfinal.plugin.activerecord.Page;
import com.jfinal.upload.UploadFile;

import javax.security.auth.login.FailedLoginException;
import java.io.File;
import java.util.*;

/**
 * 系统文件库管理
 *
 * @ClassName: JBoltFileService
 * @author: JFinal学院-小木 QQ：909854136
 * @date: 2019年3月24日 上午12:40:27
 */
public class JBoltFileService extends JBoltBaseService<JboltFile> {
    private final JboltFile dao = new JboltFile().dao();

    @Override
    protected JboltFile dao() {
        return dao;
    }


    public Page<JboltFile> paginateAdminData(int pageNumber, int pageSize) {
        return paginate("id", "desc", pageNumber, pageSize);
    }


    /**
     * 保存文件
     *
     * @param file
     * @param uploadPath
     * @param fileName
     * @param linkId
     * @return
     */
    public Ret saveFile(UploadFile file, String uploadPath, String fileName, Long linkId) {
        if (file == null || notOk(uploadPath)) {
            return fail(JBoltMsg.PARAM_ERROR);
        }
        File realFile = file.getFile();
        if (!realFile.exists() || !realFile.isFile()) {
            return fail("上传内容存储异常");
        }

        if (!file.getFileName().equals(fileName)) {
            String newPath = realFile.getAbsolutePath().replace(file.getFileName(), fileName);
            if (FileUtil.exist(newPath)) {
                fileName = newFileName(realFile.getParentFile().getAbsolutePath(), fileName);
            }
            realFile = FileUtil.rename(realFile, fileName, false);
        }

        String fileSuffix = FileTypeUtil.getType(realFile);
        int fileType = autoProcessFileType(fileSuffix);
        String localPath = realFile.getAbsolutePath();
        String localUrl = FileUtil.normalize(JBoltRealUrlUtil.get(JFinal.me().getConstants().getBaseUploadPath() + JBoltConst.SLASH + uploadPath + JBoltConst.SLASH + fileName));
        localPath = FileUtil.normalize(localPath);
        JboltFile jboltFile = new JboltFile();
        jboltFile.setObjectUserId(JBoltUserKit.getUserId());
        jboltFile.setCreateTime(new Date());
        jboltFile.setFileName(fileName);
        jboltFile.setLocalPath(localPath);
        jboltFile.setLocalUrl(localUrl);
        long fileSize = FileUtil.size(realFile);
        jboltFile.setFileSize((int) fileSize);
        jboltFile.setFileType(fileType);
        jboltFile.setFileSuffix(fileSuffix);
        if (isOk(linkId)) {
            jboltFile.setLinkId(linkId);
        }
        boolean success = jboltFile.save();
        if (!success) {
            return fail("文件保存失败");
        }
        return successWithData(jboltFile);
    }

    private String newFileName(String directory, String fileName) {
        File file = new File(directory + "/" + fileName);
        int count = 1;
        String newFilename = fileName;
        while (file.exists()) {
            int dotIndex = fileName.lastIndexOf(".");
            String extension = "";
            if (dotIndex != -1) {
                extension = fileName.substring(dotIndex);
                newFilename = fileName.substring(0, dotIndex) + "_" + count + extension;
            } else {
                newFilename = fileName + "_" + count;
            }

            file = new File(directory + newFilename);
            count++;
        }
        return newFilename;
    }

    private static Map<String, Integer> FILE_TYPE_MAP = new HashMap<>();

    static {
        FILE_TYPE_MAP.put("jpg", JboltFile.FILE_TYPE_IMAGE);
        FILE_TYPE_MAP.put("png", JboltFile.FILE_TYPE_IMAGE);
        FILE_TYPE_MAP.put("jpeg", JboltFile.FILE_TYPE_IMAGE);
        FILE_TYPE_MAP.put("gif", JboltFile.FILE_TYPE_IMAGE);
        FILE_TYPE_MAP.put("bmp", JboltFile.FILE_TYPE_IMAGE);
        FILE_TYPE_MAP.put("webp", JboltFile.FILE_TYPE_IMAGE);
        FILE_TYPE_MAP.put("tif", JboltFile.FILE_TYPE_IMAGE);

        FILE_TYPE_MAP.put("txt", JboltFile.FILE_TYPE_OFFICE);
        FILE_TYPE_MAP.put("pdf", JboltFile.FILE_TYPE_OFFICE);
        FILE_TYPE_MAP.put("doc", JboltFile.FILE_TYPE_OFFICE);
        FILE_TYPE_MAP.put("docx", JboltFile.FILE_TYPE_OFFICE);
        FILE_TYPE_MAP.put("xls", JboltFile.FILE_TYPE_OFFICE);
        FILE_TYPE_MAP.put("xlsx", JboltFile.FILE_TYPE_OFFICE);
        FILE_TYPE_MAP.put("ppt", JboltFile.FILE_TYPE_OFFICE);
        FILE_TYPE_MAP.put("pptx", JboltFile.FILE_TYPE_OFFICE);
        FILE_TYPE_MAP.put("ppts", JboltFile.FILE_TYPE_OFFICE);

        FILE_TYPE_MAP.put("mp3", JboltFile.FILE_TYPE_AUDIO);
        FILE_TYPE_MAP.put("aac", JboltFile.FILE_TYPE_AUDIO);
        FILE_TYPE_MAP.put("ogg", JboltFile.FILE_TYPE_AUDIO);
        FILE_TYPE_MAP.put("wav", JboltFile.FILE_TYPE_AUDIO);
        FILE_TYPE_MAP.put("flac", JboltFile.FILE_TYPE_AUDIO);
        FILE_TYPE_MAP.put("alac", JboltFile.FILE_TYPE_AUDIO);
        FILE_TYPE_MAP.put("aif", JboltFile.FILE_TYPE_AUDIO);
        FILE_TYPE_MAP.put("ape", JboltFile.FILE_TYPE_AUDIO);
        FILE_TYPE_MAP.put("wv", JboltFile.FILE_TYPE_AUDIO);
        FILE_TYPE_MAP.put("opus", JboltFile.FILE_TYPE_AUDIO);
        FILE_TYPE_MAP.put("am", JboltFile.FILE_TYPE_AUDIO);

        FILE_TYPE_MAP.put("mp4", JboltFile.FILE_TYPE_VEDIO);
        FILE_TYPE_MAP.put("avi", JboltFile.FILE_TYPE_VEDIO);
        FILE_TYPE_MAP.put("mpg", JboltFile.FILE_TYPE_VEDIO);
        FILE_TYPE_MAP.put("3gp", JboltFile.FILE_TYPE_VEDIO);
        FILE_TYPE_MAP.put("rm", JboltFile.FILE_TYPE_VEDIO);
        FILE_TYPE_MAP.put("rmvb", JboltFile.FILE_TYPE_VEDIO);
        FILE_TYPE_MAP.put("wmv", JboltFile.FILE_TYPE_VEDIO);
        FILE_TYPE_MAP.put("mov", JboltFile.FILE_TYPE_VEDIO);
        FILE_TYPE_MAP.put("flv", JboltFile.FILE_TYPE_VEDIO);
        FILE_TYPE_MAP.put("qsv", JboltFile.FILE_TYPE_VEDIO);
        FILE_TYPE_MAP.put("kux", JboltFile.FILE_TYPE_VEDIO);

        FILE_TYPE_MAP.put("psd", JboltFile.FILE_TYPE_DESIGN);
        FILE_TYPE_MAP.put("ai", JboltFile.FILE_TYPE_DESIGN);
        FILE_TYPE_MAP.put("cad", JboltFile.FILE_TYPE_DESIGN);
        FILE_TYPE_MAP.put("c4d", JboltFile.FILE_TYPE_DESIGN);
        FILE_TYPE_MAP.put("max", JboltFile.FILE_TYPE_DESIGN);
        FILE_TYPE_MAP.put("prproj", JboltFile.FILE_TYPE_DESIGN);
        FILE_TYPE_MAP.put("au", JboltFile.FILE_TYPE_DESIGN);


        FILE_TYPE_MAP.put("zip", JboltFile.FILE_TYPE_COMPRESSED);
        FILE_TYPE_MAP.put("rar", JboltFile.FILE_TYPE_COMPRESSED);
        FILE_TYPE_MAP.put("gz", JboltFile.FILE_TYPE_COMPRESSED);
        FILE_TYPE_MAP.put("tar", JboltFile.FILE_TYPE_COMPRESSED);
        FILE_TYPE_MAP.put("7z", JboltFile.FILE_TYPE_COMPRESSED);
        FILE_TYPE_MAP.put("arj", JboltFile.FILE_TYPE_COMPRESSED);
        FILE_TYPE_MAP.put("bz2", JboltFile.FILE_TYPE_COMPRESSED);
        FILE_TYPE_MAP.put("gzi", JboltFile.FILE_TYPE_COMPRESSED);
    }

    private Integer autoProcessFileType(String fileSuffix) {
        if (notOk(fileSuffix)) {
            return JboltFile.FILE_TYPE_ATTACHMENT;
        }
        Integer type = FILE_TYPE_MAP.get(fileSuffix);
        if (notOk(type)) {
            return JboltFile.FILE_TYPE_ATTACHMENT;
        }
        return type;
    }

    /**
     * 根据IDs获取数据
     *
     * @param ids
     * @return
     */
    public List<JboltFile> getListByIds(String ids) {
        if (notOk(ids)) {
            return Collections.emptyList();
        }
        return find(selectSql().in("id", ids));
    }


    @Override
    protected int systemLogTargetType() {
        return JBoltSystemLogTargetType.JBOLT_FILE.getValue();
    }

    /**
     * 删除数据 并删除物理路径指向的文件
     *
     * @param id
     * @param delRealFile
     * @return
     */
    public Ret deleteFileById(Object id, boolean delRealFile) {
        if (notOk(id)) {
            return fail(JBoltMsg.PARAM_ERROR);
        }
        JboltFile jboltFile = findById(id);
        if (jboltFile == null) {
            return fail(JBoltMsg.DATA_NOT_EXIST);
        }
        if (!delRealFile) {
            return SUCCESS;
        }
        boolean exist = FileUtil.exist(jboltFile.getLocalPath());
        if (!exist) {
            return SUCCESS;
        }
        boolean success = FileUtil.del(jboltFile.getLocalPath());
        return ret(success);
    }

    /**
     * 删除数据 并删除物理路径指向的文件
     *
     * @param filePath
     * @param delRealFile
     * @return
     */
    public Ret deleteFileByLocalPath(String filePath, boolean delRealFile) {
        if (notOk(filePath)) {
            return fail(JBoltMsg.PARAM_ERROR);
        }
        Ret ret = deleteBy(Okv.by("local_path", filePath));
        if (ret.isFail()) {
            return ret;
        }
        if (!delRealFile) {
            return SUCCESS;
        }
        boolean exist = FileUtil.exist(filePath);
        if (!exist) {
            return SUCCESS;
        }
        boolean success = JBoltUploadFileUtil.delete(filePath);
        return ret(success);
    }

    /**
     * 删除数据 并删除物理路径指向的文件
     *
     * @param url
     * @param delRealFile
     * @return
     */
    public Ret deleteFileByLocalUrl(String url, boolean delRealFile) {
        if (notOk(url)) {
            return fail(JBoltMsg.PARAM_ERROR);
        }
        List<JboltFile> jboltFiles = getCommonList(Okv.by("local_url", url));
        if (notOk(jboltFiles)) {
            return SUCCESS;
        }
        Ret ret = deleteBy(Okv.by("local_url", url));
        if (ret.isFail()) {
            return ret;
        }
        if (!delRealFile) {
            return SUCCESS;
        }
        for (JboltFile jboltFile : jboltFiles) {
            if (FileUtil.exist(jboltFile.getLocalPath())) {
                JBoltUploadFileUtil.delete(jboltFile.getLocalPath());
            }
        }
        return SUCCESS;

    }

}
